package com.ruoyi.api;

import com.alibaba.fastjson.JSONArray;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.api.activeMQ.JmsProducer;
import com.ruoyi.common.constant.ApiConstants;
import com.ruoyi.common.dto.AppController;
import com.ruoyi.common.dto.AuthTokenException;
import com.ruoyi.common.utils.pay.*;
import com.ruoyi.common.utils.OrderUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.interceptor.annotation.IgnoreAuth;
import com.ruoyi.framework.interceptor.annotation.LoginUserId;
import com.ruoyi.framework.interceptor.annotation.RepeatSubmit;
import com.ruoyi.project.course.courseInfo.service.ICourseInfoService;
import com.ruoyi.project.mall.carInfo.domain.CarInfo;
import com.ruoyi.project.mall.courseMark.domain.CourseMark;
import com.ruoyi.project.mall.courseMark.domain.CourseSpecific;
import com.ruoyi.project.mall.courseMark.service.ICourseMarkService;
import com.ruoyi.project.mall.order.domain.Order;
import com.ruoyi.project.mall.order.service.IOrderService;
import com.ruoyi.project.mall.orderDetail.domain.OrderDetail;
import com.ruoyi.project.mall.orderDetail.service.IOrderDetailService;
import com.ruoyi.project.mall.carInfo.service.ICarInfoService;
import com.ruoyi.project.stu.collectMark.domain.StuCollectMark;
import com.ruoyi.project.stu.collectMark.service.IStuCollectMarkService;
import com.ruoyi.project.tg.scanQrcode.service.ITgScanQrcodeService;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;


/**
 * @author ywh
 * @date 2021/5/8
 * @desc 购买课程
 */
@RestController
@RequestMapping("/api/mall")
public class MallController extends AppController {

    private static Logger logger = LoggerFactory.getLogger(MallController.class);

    @Autowired
    private ICourseInfoService courseInfoService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private WxPayService wxPayService;


    @Autowired
    private ICourseMarkService courseMarkService;

    @Autowired
    private IOrderDetailService orderDetailService;

    @Autowired
    private ICarInfoService carInfoService;

    @Autowired
    private ITgScanQrcodeService tgScanQrcodeService;

    @Autowired
    private IStuCollectMarkService stuCollectMarkService;

    @Autowired
    private JmsProducer jmsProducer;

    @Autowired
    private WXPayUtils wxPayUtils;




    /**
     * 在售课程选择
     *
     * @return
     */
    @RequestMapping("/querySellCourseList")
    @IgnoreAuth
    public Object querySellCourseList(Integer pageNum, Integer pageSize) {
        if (StringUtils.isNull(pageNum) || StringUtils.isNull(pageSize)) {
            return writeResultFailure("缺少参数传递");
        }
        startPage();
        List<CourseMark> list = courseMarkService.querySellCourseList();
        return writeResultRep(getDataTable(list));
    }


    /**
     * 课程营销详情
     *
     * @param sellId
     * @return
     */
    @RequestMapping("/selectCourseMarkById")
    public Object selectCourseMarkById(@LoginUserId Long stuId, Long sellId) {
        if (StringUtils.isNull(sellId)) {
            return toResponsFail("缺少参数");
        }
        CourseMark courseMark = courseMarkService.selectCourseMarkById(sellId);
        if (StringUtils.isNull(courseMark) || courseMark.getStatus().equals("1")){
            return toResponsFail("此课程不存在");
        }
        StuCollectMark stuCollectMark = new StuCollectMark();
        stuCollectMark.setSellId(sellId);
        stuCollectMark.setStuId(stuId);
        List<StuCollectMark> stuCollectMarks = stuCollectMarkService.selectStuCollectMarkList(stuCollectMark);
        if (stuCollectMarks.size()>0){
            courseMark.setCollectId(stuCollectMarks.get(0).getCollectId());
        }

        return writeResultRep(courseMark);
    }


    /**
     * 加入购物车
     * @param stuId
     * @ sellId
     * @ courseId
     * @ specificId
     * @ proNum
     * @return
     */
    @RequestMapping("/addCar")
    @RepeatSubmit
    public Object addCar(@LoginUserId Long stuId,CarInfo carInfo) {
        if (StringUtils.isNull(carInfo.getSellId()) || StringUtils.isNull(carInfo.getCourseId())
                || StringUtils.isNull(carInfo.getSpecificId()) || StringUtils.isNull(carInfo.getProNum())){
            return toResponsFail("缺少参数");
        }

        carInfo.setStuId(stuId);
        List<CarInfo> list = carInfoService.selectCarInfoList(carInfo);
        if (list.size()>0){
            carInfo = list.get(0);
            carInfo.setProNum(carInfo.getProNum()+1);
            carInfoService.updateCarInfo(carInfo);
        }else {
            carInfo.setProNum(1);
            carInfoService.insertCarInfo(carInfo);
        }
        return writeResultRep();
    }

    /**
     * 我的购物车列表
     * @param stuId
     * @return
     */
    @RequestMapping("/selectCarInfoList")
    public Object selectCarInfoList(@LoginUserId Long stuId) {
        CarInfo carInfo = new CarInfo();
        carInfo.setStuId(stuId);
        List<CarInfo> list = carInfoService.selectCarInfoList(carInfo);
        /*for (CarInfo info : list) {
            info.setSpecificList(courseMarkService.querySpecificListBySellId(info.getSellId()));
        }*/
        return writeResultRep(list);
    }

    /**
     * 删除购物车
     * carId 购物车主键
     * */
    @RequestMapping("/deleteCarInfoById")
    @RepeatSubmit
    public Object deleteCarInfoById(@LoginUserId Long stuId,Long carId) {
        carInfoService.deleteCarInfoById(carId);
        return writeResultRep();
    }

    /**
     * 修改购物车商品数量
     * @param carId
     * @return
     */
    @RequestMapping("/editCarNum")
    @IgnoreAuth
    @RepeatSubmit
    public Object editCarNum(Long carId,Integer proNum) {
        if (StringUtils.isNull(carId) || StringUtils.isNull(proNum)){
            return toResponsFail("缺少参数");
        }
        CarInfo carInfo = new CarInfo();
        carInfo.setCarId(carId);
        carInfo.setProNum(proNum);
        carInfoService.updateCarInfo(carInfo);
        return writeResultRep();
    }


    /**
     * 商品加入收藏
     */
    @RequestMapping("/toCollect")
    @RepeatSubmit
    public Object toCollect(@LoginUserId Long stuId,Long sellId) {
        StuCollectMark stuCollectMark = new StuCollectMark();
        stuCollectMark.setStuId(stuId);
        stuCollectMark.setSellId(sellId);
        List<StuCollectMark> stuCollectMarks = stuCollectMarkService.selectStuCollectMarkList(stuCollectMark);
        if (stuCollectMarks.size()==0){
            stuCollectMarkService.insertStuCollectMark(stuCollectMark);
        }
        return writeResultRep();
    }

    /**
     * 取消收藏
     */
    @RequestMapping("/cancelCollect")
    @RepeatSubmit
    @IgnoreAuth
    public Object cancelCollect(Long collectId) {
        stuCollectMarkService.deleteStuCollectMarkById(collectId);
        return writeResultRep();
    }

    /**
     * 营销课程收藏列表
     */
    @RequestMapping("/myCollectList")
    @RepeatSubmit
    public Object myCollectList(@LoginUserId Long stuId,Integer pageNum,Integer pageSize) {
        if (StringUtils.isNull(pageNum) || StringUtils.isNull(pageSize)) {
            return writeResultFailure("缺少参数传递");
        }
        startPage();
        List<CourseMark> list = stuCollectMarkService.myCollectList(stuId);
        return writeResultRep(getDataTable(list));
    }


    /**
     * 取消/删除订单
      * @param stuId
     * @param orderId
     * @return
     */
    @RequestMapping("/cancelOrder")
    @RepeatSubmit
    public Object cancelOrder (@LoginUserId Long stuId,Long orderId){
        if (StringUtils.isNull(orderId)){
            return toResponsFail("缺少参数");
        }
        Order order = orderService.selectOrderById(orderId);
        if (order.getStuId().intValue()!=stuId.intValue() ){
            return toResponsFail("订单信息有误");
        }

        if (order.getStatus().equals(ApiConstants.PAY_OK)){
            order.setDelFlag("1");
            orderService.updateOrder(order);
        }else {
            orderService.deleteOrderById(orderId);
        }

        return writeResultRep();
    }

    /**
     * 分页查询我的订单
     * @param stuId
     * @param orderStatus   (Y/N)
     * @return
     */
    @RequestMapping("/selectMyOrderList")
    @RepeatSubmit
    public Object selectMyOrderList (@LoginUserId Long stuId,String orderStatus,Integer pageNum,Integer pageSize){
        if (StringUtils.isEmpty(orderStatus) || StringUtils.isNull(pageNum) || StringUtils.isNull(pageSize)){
            return toResponsFail("缺少参数");
        }
        orderStatus = orderStatus.toLowerCase();
        startPage();
        List<Order> orders = orderService.selectMyOrderList(stuId,orderStatus);
        for (Order order : orders) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(order.getOrderId());
            List<OrderDetail> details = orderDetailService.selectOrderDetailList(orderDetail);
            order.setDetailList(details);
        }
        return writeResultRep(getDataTable(orders));
    }


    /**
     * 下单
     * sellId
     * courseId
     * specificId
     * @return
     */
    @RequestMapping("/toOrder")
    @RepeatSubmit
    @Transactional
    public Object toOrder(@LoginUserId Long stuId, String sellStr, BigDecimal totalPrice,String carIds) {
        if (StringUtils.isEmpty(sellStr) || StringUtils.isNull(totalPrice)) {
            return toResponsFail("缺少参数");
        }
        List<OrderDetail> list = null;
        try {
            list = JSONArray.parseArray(sellStr, OrderDetail.class);
        } catch (Exception e) {
            e.printStackTrace();
            return toResponsFail("json字符串解析失败");
        }
        BigDecimal priceSum = new BigDecimal("0");
        for (OrderDetail orderDetail : list) {
            CourseMark courseMark = courseMarkService.selectCourseMarkById(orderDetail.getSellId());
            if (courseMark.getStatus().equals("1")){
                return toResponsFail("商品已下架");
            }
            Long specificId = orderDetail.getSpecificId();
            CourseSpecific specific = courseMarkService.selectSpecificById(specificId);
            int residueNum = specific.getTotalNum() - specific.getSellNum();
            if (residueNum < orderDetail.getNum()) {
                return toResponsFail("报名人数已上线");
            }
            BigDecimal price = specific.getPrice().multiply(new BigDecimal(orderDetail.getNum()));
            orderDetail.setBeforePrice(specific.getPrice());    //单价
            orderDetail.setLastPrice(specific.getPrice());
            orderDetail.setFirstLevel(courseMark.getFirstLevel());
            orderDetail.setSecLevel(courseMark.getSecLevel());
            priceSum =priceSum.add(price);
        }
        if (totalPrice.doubleValue() != priceSum.doubleValue()) {
            return toResponsFail("价格有误");
        }
        Order order = new Order();
        order.setStuId(stuId);
        order.setOrderNo(OrderUtil.getGoodsOrderNo());
        order.setOrderPrice(totalPrice);
        order.setPayPrice(totalPrice);
        order.setStatus(ApiConstants.NO_PAY);
        int i = orderService.insertOrder(order);
        if (i>0){
            orderDetailService.batchOrderSpecific(list, order.getOrderId());
            if (StringUtils.isNotEmpty(carIds)){
                carInfoService.deleteCarInfoByIds(carIds);
            }
            return writeResultRep(order.getOrderId());
        }
        return toResponsFail("系统错误");
    }

    /**
     * 订单详情
     * @param stuId
     * @param orderId
     * @return
     */
    @RequestMapping("/selectOrderById")
    @RepeatSubmit
    public Object selectOrderById (@LoginUserId Long stuId,Long orderId){
        if ( StringUtils.isNull(orderId) ){
            return toResponsFail("缺少参数");
        }
        Order order = orderService.selectOrderById(orderId);
        if (StringUtils.isNull(order) || order.getStuId().intValue()!=stuId.intValue()){
            return toResponsFail("订单信息有误");
        }
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderId);
        List<OrderDetail> details = orderDetailService.selectOrderDetailList(orderDetail);
        order.setDetailList(details);
        return writeResultRep(order);
    }


    /**
     * 去支付
     * orderId
     * payType 线上微信-2   线上支付宝-3
     */
    @RequestMapping("/toPay")
    @RepeatSubmit
    @Transactional
    public Object toPay(@LoginUserId Long stuId, Long orderId, String payType) {
        if (StringUtils.isNull(orderId)) {
            return toResponsFail("缺少参数");
        }
        Order order = orderService.selectOrderById(orderId);
        if (StringUtils.isNull(order) || order.getStuId().longValue() != stuId.longValue() ) {
            return toResponsFail("订单不存在");
        }

        //1.未提交过支付  判断剩余量
        if (order.getStatus().equals(ApiConstants.NO_PAY)){
            OrderDetail item = new OrderDetail();
            item.setOrderId(order.getOrderId());
            List<OrderDetail> details = orderDetailService.selectOrderDetailList(item);
            for (OrderDetail detail : details) {
                Long specificId = detail.getSpecificId();
                CourseSpecific specific = courseMarkService.selectSpecificById(specificId);
                int residueNum = specific.getTotalNum() - specific.getSellNum();   //剩余名额
                if (residueNum < detail.getNum()) {
                    return toResponsFail("报名人数已上线");
                }
                courseMarkService.reduceStock(detail.getSpecificId(), detail.getNum());
            }
        }

        //2.填写订单的提交支付单号
        String payNo = String.valueOf(System.currentTimeMillis());
        BigDecimal orderPrice = order.getOrderPrice();
        order.setPayNo(payNo);
        order.setStatus(ApiConstants.PAY_ING);
        orderService.updateOrder(order);

        if (ApiConstants.WECHAT_PAY.equals(payType)) {    /***微信支付*/
            try {
                Map resultMap = wxPayUtils.toAppPay(orderPrice, payNo, orderId);
                /*加入延迟队列*/
                jmsProducer.delaySend(payNo,ApiConstants.DELAY_TIME);
                return resultMap;
            } catch (Exception e) {
                throw new AuthTokenException("微信支付系统异常");
            }

        } else if (ApiConstants.ALI_PAY.equals(payType)) {   /***支付宝支付*/
            AlipayTradeAppPayRequest aliPayRequest = AliPayUtils.toAppPay(orderPrice, payNo, orderId);
            try {
                //这里和普通的接口调用不同，使用的是sdkExecute
                AlipayTradeAppPayResponse response = AlipayConfig.getAlipayClient().sdkExecute(aliPayRequest);
                String result = response.getBody();
                /*加入延迟队列*/
                jmsProducer.delaySend(payNo,ApiConstants.DELAY_TIME);
                return writeResultRep(result);
            } catch (AlipayApiException e) {
                throw new AuthTokenException("支付宝支付系统异常");
            }
        } else {
            return toResponsFail("传递支付类型有误");
        }
    }


    /**
     * 微信支付回调
     *
     * @param xmlData
     * @return
     */
    @PostMapping(value = "/wxNotify")
    @ApiOperation(value = "异步通知", notes = "异步通知")
    @Transactional
    public String payNotify(@RequestBody String xmlData) {
        try {
            WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            String transactionNo = notifyResult.getTransactionId();   //交易流水号
            String outTradeNo = notifyResult.getOutTradeNo();   //提交的编号
            Order order = orderService.selectOrderByTrateNo(outTradeNo);
            if (StringUtils.isNotNull(order)) {
                //检测订单是否已经为已支付状态，防止多次回调
                if (order.getStatus().equals(ApiConstants.PAY_OK)) {
                    //已经支付
                    return WxPayNotifyResponse.success("处理成功!");
                }
                /******************修改订单状态************************/
                order.setPayType(ApiConstants.WECHAT_PAY);
                order.setTrateNo(transactionNo);
                int i = orderService.toPayOk(order);
                if (i > 0) {
                    //回调的逻辑操作都成功
                    return WxPayNotifyResponse.success("处理成功!");
                }
            }else {
                logger.error("没有处理微信回调业务,params:{}",notifyResult);
            }
        } catch (WxPayException e) {
            logger.error("微信回调发生错误,errorMsg:{}", e.getMessage());
        }

        return WxPayNotifyResponse.fail("程序内部错误");
    }

    /**
     *支付宝回调
     *
     * @return
     */
    @RequestMapping("/aliPayNotify")
    @IgnoreAuth
    @Transactional
    public String aliPayNotify(HttpServletRequest request) {
        try {
            Map<String, String> params = new HashMap();
            Map requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
                //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk")
                params.put(name, valueStr);
            }

            // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)
            // 商户订单号
            String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            //验证签名
            boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE);

            Order order = orderService.selectOrderByTrateNo(outTradeNo);
            if (flag) {//验证成功
                if (trade_status.equals("TRADE_SUCCESS") || trade_status.equals("TRADE_FINISHED")) {   //支付完成
                    //根据订单编号查询订单
                    if (StringUtils.isNotNull(order)) {
                        if (order.getStatus().equals(ApiConstants.PAY_OK)) {
                            //已经支付
                            return "success";
                        }
                        /******************修改订单状态************************/
                        order.setPayType(ApiConstants.ALI_PAY);
                        order.setTrateNo(trade_no);
                        int i = orderService.toPayOk(order);
                        if (i > 0) {
                            //回调的逻辑操作都成功
                            return "success";
                        }
                    }
                }else {
                    logger.error("没有处理支付宝回调业务，支付宝交易状态：{},params:{}",trade_status,params);
                }
            } else {//验证失败
                logger.info("支付宝回调签名认证失败，signVerified=false, paramsJson:{}", params);
            }
        } catch (Exception e) {
            logger.error("支付宝回调签名认证失败,errorMsg:{}", e.getMessage());
        }
        return "failure";
    }


    /**
     * 手动回调测试使用
     * @param payNo
     * @return
     */
    @RequestMapping("/handNotify")
    @IgnoreAuth
    public String handNotify(String payNo) {
        Order order = orderService.selectOrderByTrateNo(payNo);
        order.setPayType(ApiConstants.ALI_PAY);
        order.setTrateNo("1231313211331");
        orderService.toPayOk(order);
        return "success";
    }

    /**
     * 课程分享信息预存分享信息接口
     */
    @RequestMapping("/saveCourseTgInfo")
    @RepeatSubmit
    public Object saveCourseTgInfo(@LoginUserId Long stuId,Long courseId,Long userId) {
        if(courseId == null || userId == null){
            System.out.println("当前信息预存失败，缺少参数");
            return toResponsFail("缺少参数");
        }
        tgScanQrcodeService.addScanRecord(stuId,courseId,userId);
        return writeResultRep();
    }

}
